package com.maple.common.widget

import android.content.Context
import android.text.InputFilter
import android.text.InputFilter.AllCaps
import android.text.InputFilter.LengthFilter
import android.text.InputType
import android.text.method.DigitsKeyListener
import android.util.AttributeSet
import android.util.TypedValue
import android.view.LayoutInflater
import android.widget.LinearLayout
import com.maple.common.R
import com.maple.common.databinding.WidgetInputViewBinding
import com.maple.common.ext.click
import com.maple.common.ext.textChangeFlow
import com.maple.common.log.LogUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import androidx.core.content.withStyledAttributes


/**
 * Tip:
 * Create by SeVen on 2024/3/21 9:43
 */
class InputView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) :
    LinearLayout(context, attrs, defStyleAttr) {

    private val binding: WidgetInputViewBinding

    private var isEditable: Boolean = false

    init {
        val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        binding = WidgetInputViewBinding.inflate(inflater, this, true)

        initAttrs(context, attrs)
        initView()
    }

    private fun initAttrs(context: Context, attrs: AttributeSet?) {
        attrs?.let {
            context.withStyledAttributes(attrs, R.styleable.InputView) {
                for (i in 0 until indexCount) {
                    when (val attr = getIndex(i)) {
                        R.styleable.InputView_inputTitle -> {
                            val resId = getString(attr)
                            binding.tvInputTitle.text = resId
                        }

                        R.styleable.InputView_inputTitleColor -> {
                            val color = getColor(attr, 0)
                            binding.tvInputTitle.setTextColor(color)
                        }

                        R.styleable.InputView_inputTitleSize -> {
                            val size = getDimension(attr, 0f)
                            binding.tvInputTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, size)
                        }

                        R.styleable.InputView_inputText -> {
                            val resId = getString(attr)
                            binding.etInputContent.setText(resId)
                        }

                        R.styleable.InputView_inputTextColor -> {
                            val color = getColor(attr, 0)
                            binding.etInputContent.setTextColor(color)
                        }

                        R.styleable.InputView_inputTextSize -> {
                            val size = getDimension(attr, 0f)
                            binding.etInputContent.setTextSize(TypedValue.COMPLEX_UNIT_PX, size)
                        }

                        R.styleable.InputView_inputHintText -> {
                            val resId = getString(attr)
                            binding.etInputContent.hint = resId
                        }

                        R.styleable.InputView_inputHintTextColor -> {
                            val color = getColor(attr, 0)
                            binding.etInputContent.setHintTextColor(color)
                        }

                        R.styleable.InputView_isEditable -> {
                            isEditable = getBoolean(attr, false)
                            binding.etInputContent.isFocusable = isEditable
                            binding.etInputContent.isFocusableInTouchMode = isEditable
                        }

                        R.styleable.InputView_background -> {
                            val color = getColor(attr, 0)
                            binding.root.setBackgroundColor(color)
                        }

                        R.styleable.InputView_rightIcon -> {
                            val drawable = getDrawable(attr)
                            binding.ivRightIcon.setImageDrawable(drawable)
                        }

                        R.styleable.InputView_rightIconVisible -> {
                            val show = getBoolean(attr, false)
                            val visible = if (show) VISIBLE else GONE
                            binding.ivRightIcon.visibility = visible
                        }

                        R.styleable.InputView_showDividerLine -> {
                            val show = getBoolean(attr, false)
                            val visible = if (show) VISIBLE else GONE
                            binding.dividerLine.visibility = visible
                        }

                        R.styleable.InputView_android_imeOptions -> {
                            val imeOptions = getInt(attr, 0)
                            binding.etInputContent.imeOptions = imeOptions
                        }

                        R.styleable.InputView_android_inputType -> {
                            val inputType = getInt(attr, InputType.TYPE_CLASS_TEXT)
                            binding.etInputContent.inputType = inputType
                        }

                        R.styleable.InputView_android_maxLength -> {
                            val maxLength = getInt(attr, 0)
                            binding.etInputContent.filters =
                                arrayOf<InputFilter>(LengthFilter(maxLength))
                        }

                        R.styleable.InputView_android_lines -> {
                            val lines = getInt(attr, 0)
                            binding.etInputContent.setLines(lines)
                        }

                        R.styleable.InputView_android_digits -> {
                            val digits = getString(attr)
                            binding.etInputContent.filters =
                                arrayOf(AllCaps(), LengthFilter(50))
                            binding.etInputContent.keyListener =
                                digits?.let { dig -> DigitsKeyListener.getInstance(dig) }
                        }

                        R.styleable.InputView_android_maxLines -> {
                            val maxLine = getInt(attr, 0)
                            binding.etInputContent.maxLines = maxLine
                        }

                        R.styleable.InputView_android_singleLine -> {
                            val singleLine = getBoolean(attr, false)
                            binding.etInputContent.isSingleLine = singleLine
                        }

                    }
                }
            }
        }
    }

    private fun initView() {
        binding.rlInputContentLayer.click {
            if (!isEditable) {
                onArrowRightClickListener?.invoke()
            }
        }
        binding.ivRightIcon.click {
            if (isEditable) {
                onArrowRightClickListener?.invoke()
            }
        }
    }

    @OptIn(FlowPreview::class)
    fun textChangeFlow(scope: CoroutineScope, textChange: ((String) -> Unit)? = null) {
        binding.etInputContent.textChangeFlow().debounce(300).flowOn(Dispatchers.IO).onEach {
            LogUtil.d(tag = "adapter", message = it)
            textChange?.invoke(it)
        }.launchIn(scope)
    }

    /**
     * 设置标题
     */
    fun setInputTitle(title: String) {
        binding.tvInputTitle.text = title
    }

    /**
     * 获取标题
     */
    fun getInputTitle(): String {
        return binding.tvInputTitle.text.toString()
    }

    /**
     * 设置输入内容
     */
    fun setInputContent(content: String) {
        binding.etInputContent.setText(content)
    }

    /**
     * 获取输入的内容
     */
    fun getInputContent(): String {
        return binding.etInputContent.text?.trim().toString()
    }

    /**
     * 设置提示内容
     */
    fun setInputHintText(hint: String) {
        binding.etInputContent.hint = hint
    }

    /**
     *  s是否显示右边
     */
    fun rightIconVisible(isShow: Boolean) {
        val visible = if (isShow) VISIBLE else GONE
        binding.ivRightIcon.visibility = visible
    }

    /**
     * 是否可编辑
     */
    fun setIsEditable(isEditable: Boolean) {
        this.isEditable = isEditable
        binding.etInputContent.isFocusable = isEditable
        binding.etInputContent.isFocusableInTouchMode = isEditable
    }

    private var onArrowRightClickListener: (() -> Unit)? = null

    fun setOnArrowRightClickListener(onArrowRightClickListener: (() -> Unit)?) {
        this.onArrowRightClickListener = onArrowRightClickListener
    }
}